// 接雨水-双指针
class Solution {
public:
    int trap(vector<int>& height) 
    {
        // int left = 0, right = height.size() - 1;
        // int l_max = 0, r_max = 0;

        // int res = 0;
        // while (left < right) {
        //     l_max = max(l_max, height[left]);
        //     r_max = max(r_max, height[right]);

        //     // res += min(l_max, r_max) - height[i]
        //     if (l_max < r_max) {
        //         res += l_max - height[left];

        //         left++;
        //     } else {
        //         res += r_max - height[right];
        //         right--;
        //     }
        // }
        // return res;

        int left = 0 ,right = height.size() - 1;
        int l_max = 0, r_max = 0; // 定义双指针

        int res = 0;
        while(left < right)
        {
            l_max = max(l_max, height[left]);
            r_max = max(r_max, height[right]);

            if(l_max < r_max)
            {
                res += l_max - height[left];
                left++;
            }
            else
            {
                res += r_max - height[right];
                right--;
            }
        }

        return res;
    }
};


// 盛最多水的容器-双指针
class Solution {
public:
    int maxArea(vector<int>& height) 
    {
        int left = 0, right = height.size() - 1;

        int res = 0;

        while(left < right)
        {
            int hei = min(height[left], height[right]) * (right - left); // 注意是min()

            res = max(res, hei);

            if(height[left] < height[right])
            {
                left++;
            }
            else
            {
                right--;
            }
        }

        return res;
    }
};


class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) 
    {
        // 将 A 上的盘子借助 B 移动到 C 上
        dfs(A, B, C, A.size());
    }

    void dfs(vector<int>& A, vector<int>& B, vector<int>& C, int n)
    {
        // 递归出口
        if(n == 1)
        {
            C.push_back(A.back());
            A.pop_back();
            return;
        }

        // 首先将 A 中的 n - 1 个盘子通过 A C 移动到 B 上
        dfs(A, C, B, n - 1);

        // 然后将 A 中最后一个大盘直接移动到 C 上
        C.push_back(A.back());
        A.pop_back();

        // 最后通过 A B 将 B 上的圆盘移动到C上
        dfs(B, A, C, n - 1);
    }
};

class Solution {
public:

    vector<string> res;
    string track;

    vector<string> generateParenthesis(int n) 
    {
      backtrack(n, 0, 0);

      return res;
    }

    void backtrack(int n, int left, int right)
    {
      // 结束条件
      if(track.size() == 2 * n)
      {
        res.push_back(track);
        return;
      }

      if(left < n)
      {
        track.push_back('(');
        backtrack(n, left + 1, right);
        track.pop_back();
      }

      if(right < n && right < left)
      {
        track.push_back(')');
        backtrack(n, left, right + 1);
        track.pop_back();
      }
    }
};


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:

    // BST的特性：
    // 1. 对于BST的每个节点node，都有左子树的每个节点都比node小，右子树的每个节点都比node大
    // 2. 对于BST的每个节点node，它的左右子树都是BST
    // 3. 对于BST还有一个特性就是BST的中序遍历是有序的，若先遍历左子树是升序，若先遍历右子树是降序

    int rank = 0;
    int res = 0;

    int kthSmallest(TreeNode* root, int k) 
    {
        traverse(root, k);

        return res;
    }

    void traverse(TreeNode* root, int k)
    {
        if(root == nullptr)
            return;

        traverse(root->left, k);

        // 中序遍历位置

        rank++;
        if(rank == k)
        {
            res = root->val;
            return;
        }

        traverse(root->right, k);
    }
};

class Solution {
public:
    int myAtoi(string str) 
    {
        int i = 0; // 从头开始遍历比较
        int n = str.size();
        long res = 0; // 记录结果
        int flag = 1;

        // 去除前导空格
        while(i < n && str[i] == ' ')
        {
            i++;
        }
        if(i == n)
            return res;

        // 判断符号位
        if(str[i] == '-')
        {
            flag = -1;
            i++;
        }
        else if(str[i] == '+')
        {
            flag = 1;
            i++;
        }

        // 计算数字位
        while(i < n && str[i] >= '0' && str[i] <= '9')
        {
            res = res * 10 + str[i] - '0';

            if(res > INT_MAX)
                break;
            
            i++; // 别忘记了
        }

        if((int)res != res)
            return flag == 1 ? INT_MAX : INT_MIN;

        return flag * res; 
    }
};


class Solution {
public:
    bool repeatedSubstringPattern(string s) 
    {
        string t = s + s;

        // 掐头去尾
        t.erase(t.begin());
        t.erase(t.end() - 1);

        if(t.find(s) != string::npos)
            return true;
        
        return false;
    }
};



// 饿汉模式

// class Singleton
// {
// public:
//     // 对外提供一个全局访问点
//     static Singleton* GetInstance()
//     {
//         return _sInst;
//     }

// private:
//     // 提供一个指向单例对象的static指针
//     static Singleton* _sInst;

// private:
//     // 构造函数私有以及防止拷贝
//     Singleton()
//     {}

//     Singleton(const Singleton&) = delete;

//     Singleton& operator=(const Singleton&) = delete;
// };

// // 在程序入口之前对单例对象初始化
// Singleton* Singleton::_sInst = new Singleton;


// 懒汉模式

class Singleton
{
public:
    // 对外提供一个全局访问点
    static Singleton* GetInstance()
    {
        if(nullptr == _sInst)
        {
            _mtx.lock();

            // 双检查
            if(nullptr == _sInst)
                _sInst = new Singleton;

            _mtx.unlock();
        }

        return _sInst;
    }

private:
    // 提供一个指向单例对象的static指针 和 一个互斥锁
    static Singleton *_sInst;
    static mutex _mtx;

private:
    // 构造函数私有以及防止拷贝
    Singleton()
    {}

    Singleton(const Singleton&) = delete;

    Singleton& operator=(const Singleton&) = delete;
};

// 在程序入口之前初始化单例对象为空 以及 初始化互斥锁
Singleton* Singleton::_sInst = nullptr;
mutex Singleton::_mtx;


// 最长无重复子串
// "abdsfnsd"

#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

int maxStrLength(string& s)
{
    // 统计窗口中字符的出现次数
    unordered_map<char, int> window;
    int left = 0, right = 0;

    int ret = 0; // 记录结果

    while(right < s.size())
    {
        // 即将移入窗口的字符
        char c = s[right];
        // 扩大窗口
        right++;

        window[c]++;

        // 判断左侧窗口何时收缩
        while(window[c] > 1)
        {
            // 即将移出窗口的字符
            char d = s[left];
            // 缩小窗口
            left++;

            window[d]--;
        }

        // 更新结果
        ret = max(ret, right - left);
    }

    return ret;
}

int main()
{
    string str;
    cin >> str;

    int ret = maxStrLength(str);

    cout << ret << endl;

    return 0;
}


namespace sl
{
    // 建大堆
    template<class T>
    struct less
    {
        bool operator()(const T& x, const T& y)
        {
            return x < y;
        }
    };

    // 建小堆
    template<class T> 
    struct greater
    {
        bool operator()(const T& x, const T& y)
        {
            return x > y;
        }
    };

    template<class T, class Container = vector<T>, class Compare = less<T>>
    class priority_queue
    {
    public:
        // 向上调整
        void AdjustUp(int child)
        {
            int parent = (child - 1) / 2;

            while(child >= 0)
            {
                if(_comp(_con[child], _con[parent]))
                {
                    std::swap(_con[child], _con[parent]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }

        // 向下调整
        void AdjustDown(int n, int parent)
        {
            int child = parent * 2 + 1;

            while(child < n)
            {
                while(child + 1 < n && _con[child] < _con[child + 1])
                    child++;
                
                if(_con[child], _con[parent])
                {
                    std::swap(_con[child], _con[parent]);
                    child = parent;
                    parent = child * 2 + 1;
                }
                else
                {
                    break;
                }
            }
        }

        void push(const T& val)
        {
            _con.push_back(val);
            AdjustUp(_con.size()-  1);
        }

        void pop()
        {
            std::swap(_con[0], _con[_con.size() - 1]);
            _con.pop_back();
            AdjustDown(_con.size(), 0);
        }

        T& top()
        {
            assert(!empty());

            return _con[0];
        }

        bool empty()
        {
            return _con.empty();
        }

    private:
        Container _con;
        Compare _comp;
    };
}



namespace sl
{
    // 节点类
    template<class T>
    struct _list_node
    {
        typedef _list_node<T> node;

        T _val;
        node* _prev;
        node* _next;

        _list_node(const T& val = T())
            : _val(val)
            , _prev(nullptr)
            , _next(nullptr)
        {}
    };

    // 迭代器类
    template<class T, class Ref, class Ptr>
    struct _list_iterator
    {
        typedef _list_node<T> node;
        typedef _list_iterator<T, Ref, Ptr> self;

        node* _node;

        // 前置++
        self& operator++()
        {
            _node = _node->_next;
            return *this;
        }

        // 后置++
        self operator++(int)
        {
            self tmp(*this);
            _node = _node->_next;
            return tmp;
        }

        // 前置-- 
        self& operator--()
        {
            _node = _node->_prev;
            return *this;
        }

        // 后置--
        self operator--(int)
        {
            self tmp(*this);
            _node = _node->_prev;
            return tmp;
        }

        bool operator==(const self& lt)
        {
            return _node == lt._node;
        }

        bool operator!=(const self& lt)
        {
            return _node != lt._node;
        }

        Ref operator*()
        {
            return *_node->_val;
        }

        Ptr operator->()
        {
            return &_node->_val;
        }
    };  

    // List类
    template<class T>
    class List
    {
    public:
        typedef _list_node<T> node;
        typedef _list_iterator<T, T&, T*> iterator;
        typedef _list_iterator<const T, const T&, const T*> const_iterator;

        List()
        {
            _head = new node(-1);
            _head->_prev = _head;
            _head->_next = _head;
        }

        void head_init()
        {
            _head = new node(-1);
            _head->_prev = _head;
            _head->_next = _head;
        }

        template<class InputIterator>
        List(InputIterator first, InputIterator last)
        {
            head_init();

            while(first != last)
            {
                push_back(*first);
                first++;
            }
        }

        void swap(List<T>& lt)
        {
            std::swap(_head, lt._head);
        }

        List(const List<T>& lt)
        {
            head_init();

            List<T> tmp(lt.begin(), lt.end());
            swap(tmp);
        }

        List<T>& operator=(List<T> lt)
        {
            swap(lt);
            return *this;
        }

        ~List()
        {
            clear();

            delete _head;
            _head = nullptr;
        }

        // 迭代器相关函数
        iterator begin()
        {
            return iterator(_head->_next);
        }

        iterator end()
        {
            return iterator(_head);
        }

        const_iterator begin() const
        {
            return const_iterator(_head->_next);
        }

        const_iterator end() const
        {
            return const_iterator(_head);
        }

        // 容器操作函数
        void clear()
        {
            iterator it = begin();

            while(it != end())
            {
                it = erase(it);
            }
        }

        void insert(iterator pos, const T& val)
        {
            assert(pos->_node);

            node* cur = pos->_node;
            node* prev = cur->_prev;
            node* newnode = new node(val);

            // prev newnode cur
            prev->_next = newnode;
            newnode->_prev = prev;

            newnode->next = cur;
            cur->_prev = newnode;
        }

        iterator erase(iterator pos)
        {
            assert(pos->_node);
            assert(pos != end());

            node* cur = pos->_node;
            node* prev = cur->_prev;
            node* next = cur->_next;

            delete cur;

            prev->_next = next;
            next->_prev = prev;

            return iterator(next);
        }

    private:
        node* _head;
    };
}


class Solution {
public:
    int majorityElement(vector<int>& nums) 
    {
        int target = 0; // 我们想找的目标众数
        int count = 0;  // 计数器 - 想想带电粒子的例子 - 最后一定带正电

        for(int i = 0; i < nums.size(); i++)
        {
            if(count == 0)
            {
                target = nums[i]; 

                count++;
            }
            else if(nums[i] == target)
            {
                count++;
            }
            else 
            {
                count--;
            }
        }

        return target;
    }
};


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSubStructure(TreeNode* A, TreeNode* B) 
    {
        if(A == nullptr || B == nullptr)
            return false;
        
        if(A->val == B->val && compare(A, B))
            return true;

        return isSubStructure(A->left, B)
            || isSubStructure(A->right, B);
    }

    bool compare(TreeNode* A, TreeNode* B)
    {
        if(B == nullptr)
            return true;
        
        if(A == nullptr && B != nullptr)
            return false;

        if(A->val != B->val)
            return false;

        return compare(A->left, B->left)
            && compare(A->right, B->right);
    }
};



// #include <iostream>
// #include <string>
// #include <unordered_map>

// using namespace std;

// int maxStrLength(string& s)
// {
//     // 统计窗口中字符的出现次数
//     unordered_map<char, int> window;
//     int left = 0, right = 0;

//     int ret = 0; // 记录结果

//     while(right < s.size())
//     {
//         // 即将移入窗口的字符
//         char c = s[right];
//         // 扩大窗口
//         right++;

//         window[c]++;

//         // 判断左侧窗口何时收缩
//         while(window[c] > 1)
//         {
//             // 即将移出窗口的字符
//             char d = s[left];
//             // 缩小窗口
//             left++;

//             window[d]--;
//         }

//         // 更新结果
//         ret = max(ret, right - left);
//     }

//     return ret;
// }

// int main()
// {
//     string str;
//     cin >> str;

//     int ret = maxStrLength(str);

//     cout << ret << endl;

//     return 0;
// }





#include <iostream>
#include <vector>
using namespace std;

vector<vector<int>> res; // 保存结果

void function(vector<int>& nums)
{
    int sz = nums.size();

    for(int i = 0; i < sz; i++)
    {
        int start = nums[i]; // 首元素
        int index = i; // 首元素的下标

        while(i < sz - 1 && nums[i + 1] == nums[i] + 1)
        {
            i++;
        }

        int end = nums[i]; // 尾元素

        if(index != i)
        {
            res.push_back({start, end});
        }
        else
        {
            res.push_back({start});
        }
    }
}

int main()
{
    vector<int> nums = {1, 2, 3, 5, 6, 9, 10, 11, 12, 13, 20};

    function(nums);

    for(int i = 0; i < res.size(); i++)
    {
        for(int j = 0; j < res[i].size(); j++)
        {
            cout << res[i][j] << " ";
        }
    }

    return 0;
}



